package com.cskaoyan.javase._2inner._5anonymous._0introduction;

/**
 * 本节内部类对象，本质上还是属于定义在别的类内部的一个类。
 * 但区别是：
 *      成员内部类、静态内部类和局部内部类都属于定义了一个类，后续使用还需要基于内部类创建对象。
 *      既然需要对象,那么就一步到位,直接通过语法创建这个内部类的对象,这个内部类本身叫什么,已经不重要了.
 * 而本节中的匿名内部类和Lambda表达式都是直接通过语法创建了对象。
 * 其实想一想，我们定义内部类，最终还是为了获取对象使用，
 *      所以实际开发中匿名内部和Lambda表达式会更常见和常用。
 *
 * 匿名内部类
 * 首先要明确,匿名内部类是特殊的局部内部类,是简化语法的匿名内部类,仍然定义在局部位置
 * 我们已经使用过匿名对象了，匿名对象的含义是这个对象是没有名字，没有引用指向它。
 * 那么匿名内部类，指的就是这个内部类没有名字。
 * 当然成员内部类和静态内部类没法没有名字，所以 匿名内部类指的是"没有名字的局部内部类"。
 * 是一种特殊的局部内部类。
 *
 * 思考:
 *      如果一个类是匿名的,没有名字,如何new创建它的对象呢?
 *      显然是没有办法在该匿名类的后面创建对象的,只能在定义匿名类的同时,直接new创建它的对象.
 *
 * 匿名内部类的语法:
 * // 局部位置
 * new 类名或者接口名(){
 *   // 某类名或接口名的子类的类体
 * };
 * // 局部位置
 * 解释:
 *      1.new关键字表示直接创建对象,因为这个特殊的局部内部类是匿名的,不直接创建对象,后面就创建不了了
 *      2.类名或者接口名可以写普通类,也可以写抽象类
 *      3.(重要)匿名内部类的语法中隐含了"继承"或者"实现",匿名内部类的语法是直接创建
 *          "类名或者接口名"的子类对象
 *          所谓的匿名内部类
 *          实际上是"匿名的子类内部类对象"
 *
 *      4.new关键字后面的部分:
 *              类名或者接口名(){
 *                  // 某类名或接口名的子类的类体
 *              }
 *      是匿名子类的类体
 *      在这个类体中,可以重写父类方法,也可以新增自身成员,成员特点,参考成员内部类
 *      没有static声明,但是可以定义全局常量(不触发类加载的)
 *      注: 匿名内部类当中很少会自定义新增成员,了解知道就可以了.
 *
 * 匿名内部类对象的使用:
 *      1.匿名内部类的语法本身就是得到一个对象
 *          得到类名/接口名的子类对象
 *          所以可以在语法后面直接使用
 *
 *          优点: 简单快捷,并且可以访问匿名子类独有成员
 *          缺点: 一次性的,只能用一次
 *
 *      2.用引用接收,然后使用.
 *          用语法中的"类名/接口名"作为父引用接收即可
 *
 *          优点: 不是一次性的,可以使用多次
 *          缺点: 不能访问匿名子类独有成员,而且是真的访问不了,因为无法强转
 *          而且稍微麻烦一点,因为需要用引用接收
 *
 * 以上,要根据不同的场景,来选择不同的使用方式
 * 相对而言,"直接使用"会更多一点
 * 而且如果想要访问匿名子类的成员,也必须"直接使用"
 *
 * @since 11:26
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 创建匿名对象
        new A();

        // 创建匿名类的对象,创建的是A的子类对象,但是这个子类是什么,不知道
        System.out.println(new A() {
            int a;
            private int b;
            // static int c;
            static final int D = 30;

            @Override
            void test() {
                System.out.println("我是匿名内部类的实现,我很高级!");
            }
        }.a);

        // 创建抽象类BaseB的子类对象
        BaseB b = new BaseB() {
            int a = 10;
            @Override
            public void test() {
                System.out.println("匿名内部类创建抽象类的子类对象");
            }
        };
        b.test();
        // b.a.sout


    }
}

abstract class BaseB {
    public abstract void test();
}

class A {
    void test() {
        System.out.println("A");
    }
}